/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

(function ($){
    
    $.fn.gridView = function(){
        this.each(function(index, element) {
            element.enableGridView = enableGridView;
            element.enableGridView();
        });
    };
    
    var pagesArround = 3;
    
    function enableGridView() {
        this.filters = {};
        this.startPage = this.dataset.startPage || 0;
        this.count = this.dataset.count || 10;
        this.totalItems = 0;
        this.sort = this.dataset.sort || null;
        this.service = new RemoteObject(this.dataset.service);
        this.service.listener = this;
        this.getDataLoaded = getDataLoaded;
        this.updateCellLoaded = updateCellLoaded;
        this.deleteItemLoaded = deleteItemLoaded;
        
        this.buildTableUI = buildTableUI;
        this.buildPaginator = buildPaginator;
        this.loadTableData = loadTableData;
        this.updateFilters = updateFilters;
        
        this.loadData = this.service.getAction("getData");
        this.deleteItem = this.service.getAction("deleteItem");
        
        this.updateCell = updateCell;

        
        // collect editor
        this.editors = {};
        var editors = $(this).find(".editors div");
        for (var i = 0; i < editors.length; i++) {
            var editorDiv = editors[i];
            var editor = {};
            editor.type = editorDiv.dataset.type;
            if (editor.type === "combo-box") {
                editor.displayColumn = editorDiv.dataset.displayColumn;
                editor.options = [];
                var options = $(editorDiv).find("span");
                for (var j = 0; j < options.length; j++) {
                    editor.options[j] = { 
                                            'value' : options[j].dataset.value, 
                                            'label' : options[j].innerHTML
                                        };
                }
            };
            this.editors[editorDiv.dataset.column] = editor;            
        }
        $(this).find(".editors").detach();
        
        var filters = $(this).find(".filters div").addClass("grid-cell");

        for (var i = 0; i < filters.length; i++) {
            filters[i].index = i;
            filters[i].gridView = this;
            filters[i].filterChanged = filterChanged;
            
            if ($(filters[i]).hasClass("filter")) {
                $(filters[i]).addClass("editor");
            }
        }   
        
        filters.blur(filterBlur);
        
        // get all columns
        this.columns = [];
        var columns = $(this).find(".columns div");
        $(this).find(".columns").addClass("grid-header");
        
        for (var i = 0; i < columns.length; i++) {
            this.columns[i] = { 
                        'name' : columns[i].dataset.column, 
                        'editable' : columns[i].dataset.editable
                    };
            $(columns[i]).addClass("data-" + columns[i].dataset.column)
                         .addClass("grid-cell");
            if (this.columns[i].name !== "index" || this.columns[i].name !== "delete") {
                $(columns[i]).addClass("sortable");
                columns[i].gridView = this;
                $(columns[i]).click(sortData);
            }
        }

        
        this.buildTableUI();
        this.updateFilters();
    };
    
    function filterBlur() {
        this.dataset.value = this.innerHTML;
        this.filterChanged();
    }
    
    function filterChanged(value) {
        if (value !== undefined) {
            this.dataset.value = value;
        }
        this.gridView.updateFilters();
    }
    
    function updateFilters() {
        this.filters = {};
        
        var filters = $(this).find(".filters div");
        
        for (var i = 0; i < filters.length; i++) {
            var filterValue = filters[i].dataset.value;
            if (filterValue !== undefined && filterValue !== "") {
                this.filters[this.columns[i].name] = filterValue;
                $(filters[i]).addClass("filtering");
            } else {
                $(filters[i]).removeClass("filtering");
            }
        } 
        
        this.loadTableData();
    }
    
    function sortData(){
        var order = "asc";
        if ($(this).hasClass("asc")) {
            order = "desc";
            $(this).parent().find("*").removeClass("asc").removeClass("desc");
            $(this).addClass("desc");
        } else {
            $(this).parent().find("*").removeClass("asc").removeClass("desc");
            $(this).addClass("asc");
        }
        
        this.gridView.sort = this.dataset.column + " " + order;
        this.gridView.loadTableData();
    }
    
    function updateCell(itemId, itemField, itemValue, item) {
        var updateCellAction = this.service.getAction("updateCell");
        updateCellAction.item = item;
        updateCellAction.invoke(itemId, itemField, itemValue);        
        $(item).addClass("saving");
    }

    /**
     * Update Cell
     * @param {type} data
     * @param {type} action
     * @returns {undefined}
     */
    function updateCellLoaded(data, action) {
        $(action.item).removeClass("saving");
    }
    
    function buildTableUI() {
        this.footer = $("<div class='grid-footer'></div>").insertAfter(this);
        this.paginator = $("<div class='paginator'></div>").appendTo(this.footer);
        this.buildPaginator();
    }
    
    function pageItemClick() {
        this.gridView.startPage = this.page;
        this.gridView.loadTableData();
    }
    
    function addPageItem(page, gridView) {
        var pageItem = $("<div class='previous-button page-item'>" + (page + 1) + "</div>").appendTo(gridView.paginator);
        pageItem[0].gridView = gridView;
        pageItem[0].page = page;
        pageItem.click(pageItemClick);
    }
    
    function buildPaginator() {
        // total pages
        var numPages = Math.ceil(this.totalItems / this.count);
        this.paginator.html("");
        
        if (this.startPage > 0) {
            // 
            this.previousButton = $("<div class='previous-button page-item'>&lt;</div>").appendTo(this.paginator);
            this.previousButton[0].gridView = this;
            this.previousButton[0].page = this.startPage - 1;
            this.previousButton.click(pageItemClick);
        }
        
        var start = 0;
        
        if (this.startPage - pagesArround > 0) {
            start = this.startPage - pagesArround;
        }
        
        for (var i = start; i < this.startPage; i++) {
            addPageItem(i, this);
        }
        
        $("<div class='current-page'>" + (this.startPage + 1) + "</div>").appendTo(this.paginator);
        
        for (var i = this.startPage + 1; i < numPages && i < this.startPage + pagesArround; i++) {
            addPageItem(i, this);
        }
        
        if (this.startPage < numPages - 1) {
            // 
            this.nextButton = $("<div class='previous-button page-item'>&gt;</div>").appendTo(this.paginator);
            this.nextButton[0].gridView = this;
            this.nextButton[0].page = this.startPage + 1;
            this.nextButton.click(pageItemClick);
        }
    }
    
    function loadTableData() {
        this.footer.addClass("loading");
        this.loadData.invoke(this.filters, this.startPage, this.count, this.sort);
    }
    
    function deleteItemLoaded(data, action) {
        this.loadTableData();
    }
    
    function deleteButtonClick() {
        var gridView = this.gridView;
        var itemId = this.itemId;
        new Dialog("Are you sure to delete?", "Deleting will remove this user from system.<br />You cannot undo this operation.", ["No", "Yes"], function (selectedOption){
            if (selectedOption) {
                gridView.deleteItem.invoke(itemId);
            }
        });
    }
    
    function itemClicked() {
        $(this).parent().parent().parent().addClass("changed");
        this.gridView.updateCell(this.itemId, this.fieldName, this.dataset.value, this);
    }
    
    function getDataLoaded(result, action) {
        
        var data = result.rows;
        this.totalItems = parseInt(result.count[0].count);
        
        this.footer.removeClass("loading");
        
        $(this).find(".grid-data-row").detach();

        for (var i = 0; i < data.length; i++) {
            var rowDiv = $("<div class='grid-data-row'></div>").appendTo(this);
            data[i]["index"] = parseInt(this.startPage) * parseInt(this.count) + i + 1;
            for (var j = 0; j < this.columns.length; j++) {
                var column = this.columns[j];
                var cellDiv = $("<div class='grid-cell'></div>").appendTo(rowDiv);
                cellDiv[0].gridView = this;
                cellDiv[0].itemId = data[i]['id'];
                    
                if (column.name !== 'delete') {
                    cellDiv.html(data[i][column.name]);
                    cellDiv[0].fieldName = column.name;                    
                    cellDiv.html("<span>" + cellDiv.html() + "</span>");
                    
                    if (column.editable) {
                        if (this.editors[column.name]) {
                            var editor = this.editors[column.name];
                            cellDiv.addClass("combobox");
                            var list = $("<ul class='dropdown'></ul>").appendTo(cellDiv);
                            
                            for (var k = 0; k < editor.options.length; k++) {
                                var item = $("<li><a href='#' data-value='" + editor.options[k].value + "'>" + editor.options[k].label + "</a></li>").appendTo(list);
                                var a = item.find("a")[0];
                                a.gridView = this;
                                a.itemId = data[i]['id'];
                                a.fieldName = column.name;                                
                                $(a).click(itemClicked);
                            }
                            
                        } else {
                            cellDiv.addClass("editor");
                            cellDiv.blur(onCellBlur);
                        }
                    }
                                                            
                } else {
                    cellDiv.addClass("delete");
                    cellDiv.click(deleteButtonClick);
                }
                                
            }
        }
        
        this.buildPaginator();
        normalize(this);
    }
    
    
    function onCellBlur() {
        $(this).addClass("changed");
        this.gridView.updateCell(this.itemId, this.fieldName, this.innerHTML, this);
    }
    
})(jQuery);

